import React, { Component } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { is } from 'immutable'

import { Scrollbars } from 'react-custom-scrollbars'

import { init, dispose } from 'klinecharts'

import SettingModal from './modal/SettingModal'
import themeHOC from '../../../common/themeHOC'
import Loading from '../../../../component/loading/Loading'

import { intervals } from '../intervals'
import { THEME } from '../../../../constants/constants'
import { formatValue, getContractPriceDecimalNumber } from '../../../../utils/dataUtils'

import {
  K_INTERVAL_REAL_TIME, K_INTERVAL_ONE_DAY, K_INTERVAL_ONE_MONTH, K_INTERVAL_ONE_WEEK,
  getHistoryKLineData, subscribeKLine, unsubscribeKLine
} from '../../../../redux/actions/tradeChartAction.js'

import './original-view.less'

const drawLineIcon = [
  { key: 'horizontalStraightLine', icon: 'icon-horizontal-straight-line' },
  { key: 'horizontalRayLine', icon: 'icon-horizontal-ray-line' },
  { key: 'horizontalSegmentLine', icon: 'icon-horizontal-segment-line' },
  { key: 'priceLine', icon: 'icon-price-line' },
  { key: 'verticalStraightLine', icon: 'icon-vertical-straight-line' },
  { key: 'verticalRayLine', icon: 'icon-vertical-ray-line' },
  { key: 'verticalSegmentLine', icon: 'icon-vertical-segment-line' },
  { key: 'straightLine', icon: 'icon-straight-line' },
  { key: 'rayLine', icon: 'icon-ray-line' },
  { key: 'segmentLine', icon: 'icon-segment-line' },
  { key: 'parallelStraightLine', icon: 'icon-parallel-straight-line' },
  { key: 'priceChannelLine', icon: 'icon-price-channel-line' },
  { key: 'fibonacciLine', icon: 'icon-fibonacci-line' }
]

const technicalIndicatorTypes = [
  'MA', 'VOL', 'MACD', 'BOLL', 'KDJ',
  'RSI', 'BIAS', 'BRAR', 'CCI', 'DMI',
  'CR', 'PSY', 'DMA', 'TRIX', 'OBV',
  'VR', 'WR', 'MTM', 'EMV', 'SAR'
]

@connect(state => {
  return {
    wsConnectSuccess: state.app.get('wsConnectSuccess'),
    currentContract: state.trade.market.get('currentContract'),
    currentInterval: state.trade.chart.get('currentInterval'),
    kLineData: state.trade.chart.get('kLineData')
  }
}, dispatch => {
  return bindActionCreators({
    subscribeKLine, unsubscribeKLine
  }, dispatch)
})
@themeHOC
class OriginalView extends Component {
  constructor (props) {
    super(props)
    this.windowResize = () => {
      if (this.originalView) {
        this.originalView.resize()
      }
    }
    this.state = {
      isShowTechnicalIndicator: false,
      currentTechnicalIndicatorType: 'MACD'
    }
  }

  /**
   * 获取历史数据
   */
  getHistoryData (shouldLoading, timeTo) {
    if (shouldLoading) {
      this.loading = true
      this.forceUpdate()
    }
    const { currentInterval, currentContract } = this.props
    const isNotFirst = !!timeTo
    let to = isNotFirst ? timeTo : Math.floor(new Date().getTime() / 1000)
    switch (currentInterval) {
      case K_INTERVAL_ONE_DAY: {
        to = isNotFirst ? to - 24 * 3600 : to
        break
      }
      case K_INTERVAL_ONE_WEEK: {
        to = isNotFirst ? to - 7 * 24 * 3600 : to
        break
      }
      case K_INTERVAL_ONE_MONTH: {
        to = isNotFirst ? to - 30 * 24 * 3600 : to
        break
      }
      default: {
        to = isNotFirst ? to - (+intervals[currentInterval]) * 60 : to
      }
    }
    getHistoryKLineData(
      {
        ticker: formatValue(currentContract, 'InstrumentID'),
        isInverse: formatValue(currentContract, 'IsInverse'),
        volumeMultiple: formatValue(currentContract, 'VolumeMultiple')
      },
      intervals[currentInterval], null, to,
      (klineDataList) => {
        if (this.originalView) {
          if (isNotFirst) {
            this.originalView.applyMoreData(klineDataList, false)
          } else {
            this.originalView.applyNewData(klineDataList, false)
          }
          this.loading = false
          this.forceUpdate()
        }
      }, () => {
        if (isNotFirst) {
          this.originalView.applyMoreData([], false)
        } else {
          this.originalView.applyNewData([], false)
        }
        this.loading = false
        this.forceUpdate()
      }
    )
  }

  componentDidMount () {
    const { onRef, wsConnectSuccess, currentContract, currentInterval, subscribeKLine } = this.props
    window.addEventListener('resize', this.windowResize, false)
    onRef(this)
    this.originalView = init('k_chart')
    this.originalView.loadMore(timestamp => {
      this.getHistoryData(false, timestamp / 1000)
    })
    this.originalView.createTechnicalIndicator('VOL', 80)
    this.setTheme()
    this.setChartType(this.props.currentInterval)
    if (wsConnectSuccess && currentContract) {
      const decimal = getContractPriceDecimalNumber(currentContract)
      this.originalView.setPrecision(decimal, 0)
      this.getHistoryData(true)
      subscribeKLine(currentContract, intervals[currentInterval])
    }
  }

  componentDidUpdate (prevProps, prevState, snapshot) {
    const { theme, wsConnectSuccess, currentContract, currentInterval, kLineData, subscribeKLine, unsubscribeKLine } = this.props
    if ((!prevProps.wsConnectSuccess && wsConnectSuccess) ||
      currentInterval !== prevProps.currentInterval ||
      formatValue(currentContract, 'InstrumentID') !== formatValue(prevProps.currentContract, 'InstrumentID')) {
      if (this.originalView) {
        this.setChartType(currentInterval)
        const decimal = getContractPriceDecimalNumber(currentContract)
        this.originalView.setPrecision(decimal, 0)
        if (currentContract) {
          this.getHistoryData(true)
        }
        unsubscribeKLine(prevProps.currentContract, intervals[prevProps.currentInterval])
        subscribeKLine(currentContract, intervals[currentInterval])
      }
    }
    if (theme !== prevProps.theme) {
      this.setTheme()
    }
    if (!is(prevProps.kLineData, kLineData) && kLineData && this.originalView) {
      this.originalView.updateData(kLineData.toJS())
    }
  }

  /**
   * 设置主图
   */
  setTheme () {
    const { theme } = this.props
    const isDay = theme === THEME.DAY
    const mainColor = isDay ? '#50535E' : '#D9D9D9'
    const secondColor = isDay ? '#989696' : '#888888'
    const gridColor = isDay ? '#ededed' : '#393939'
    const crossTextFillColor = isDay ? '#666666' : '#505050'
    const crossTextColor = isDay ? '#FFFFFF' : '#FFFFFF'
    const style = {
      grid: {
        horizontal: {
          color: gridColor
        }
      },
      candleStick: {
        priceMark: {
          high: {
            color: mainColor
          },
          low: {
            color: mainColor
          }
        }
      },
      technicalIndicator: {
        line: {
          colors: [mainColor, '#F5A623', '#F601FF', '#1587DD', '#1e88e5']
        }
      },
      xAxis: {
        minHeight: 26,
        axisLine: {
          color: secondColor
        },
        tickText: {
          color: mainColor
        },
        tickLine: {
          color: secondColor
        }
      },
      yAxis: {
        axisLine: {
          color: secondColor
        },
        tickText: {
          color: mainColor
        },
        tickLine: {
          color: secondColor
        }
      },
      separator: {
        color: secondColor
      },
      floatLayer: {
        crossHair: {
          horizontal: {
            line: {
              color: secondColor
            },
            text: {
              color: crossTextColor,
              borderColor: crossTextFillColor,
              backgroundColor: crossTextFillColor
            }
          },
          vertical: {
            line: {
              color: secondColor
            },
            text: {
              color: crossTextColor,
              borderColor: crossTextFillColor,
              backgroundColor: crossTextFillColor
            }
          }
        },
        prompt: {
          candleStick: {
            text: {
              color: mainColor
            }
          },
          technicalIndicator: {
            text: {
              color: mainColor
            }
          }
        }
      }
    }
    this.originalView.setStyleOptions(style)
  }

  /**
   * 设置图表类型
   * @param interval
   */
  setChartType (interval) {
    let chartType
    if (interval === K_INTERVAL_REAL_TIME) {
      chartType = 'real_time'
    } else {
      chartType = 'candle_stick'
    }
    this.originalView.setCandleStickChartType(chartType)
  }

  /**
   * 设置蜡烛图样式
   * @param style
   */
  setCandleStickStyle (style) {
    this.originalView.setStyleOptions({
      candleStick: {
        bar: {
          style
        }
      }
    })
  }

  setCandleTechnicalIndicatorType (type) {
    this.originalView.setCandleStickTechnicalIndicatorType(type)
  }

  showTechnicalIndicator () {
    const isShowTechnicalIndicator = !this.state.isShowTechnicalIndicator
    if (isShowTechnicalIndicator) {
      this.technicalIndicatorTag = this.originalView.createTechnicalIndicator(this.state.currentTechnicalIndicatorType, 80)
    } else {
      this.originalView.removeTechnicalIndicator(this.technicalIndicatorTag)
    }
    this.setState({ isShowTechnicalIndicator }, () => {
      this.originalView.resize()
    })
  }

  screenShot () {
    const url = this.originalView.getConvertPictureUrl(true, true)
    const a = document.createElement('a')
    a.download = 'screenShot'
    a.href = url
    document.body.appendChild(a)
    a.click()
    a.remove()
  }

  /**
   * 显示设置弹框
   */
  showSettingDialog () {
    this.showIndicatorModal = false
    this.showSettingModal = !this.showSettingModal
    this.forceUpdate()
  }

  /**
   * 显示指标弹框
   */
  showIndicatorDialog () {
    this.showIndicatorModal = !this.showIndicatorModal
    this.showSettingModal = false
    this.forceUpdate()
  }

  changeTechnicalIndicator = (technicalIndicatorType) => () => {
    if (this.state.currentTechnicalIndicatorType !== technicalIndicatorType) {
      this.originalView.setTechnicalIndicatorType(this.technicalIndicatorTag, technicalIndicatorType)
      this.setState({
        currentTechnicalIndicatorType: technicalIndicatorType
      })
    }
  }

  /**
   * 关闭指标弹框
   */
  closeIndicatorModal = () => {
    this.showIndicatorModal = false
    this.forceUpdate()
  }

  /**
   * 关闭设置弹框
   */
  closeSettingModal = () => {
    this.showSettingModal = false
    this.forceUpdate()
  }

  /**
   * 指标选择事件
   * @param indicatorType
   */
  onIndicatorSelected = (indicatorType) => {
    if (this.originalView) {
      this.originalView.setTechnicalIndicatorType(this.tag, indicatorType)
      this.showIndicatorModal = false
      this.forceUpdate()
    }
  }

  componentWillUnmount () {
    window.removeEventListener('resize', this.windowResize, false)
    dispose('k_chart')
    this.originalView = null
  }

  /**
   * 绘制图形
   * @param markerType
   * @returns {function(...[*]=)}
   */
  drawMark = (markerType) => () => {
    if (this.originalView) {
      this.originalView.addGraphicMark(markerType)
    }
  }

  /**
   * 删除点击事件
   */
  onDelete = () => {
    if (this.originalView) {
      this.originalView.removeAllGraphicMark()
    }
  }

  render () {
    const { theme } = this.props
    return (
      <div className={`trade-chart-content-container-${theme}`}>
        <ul className="trade-chart-draw-toolbar-container">
          <Scrollbars>
            {
              drawLineIcon.map(({ key, icon }) => {
                return (
                  <li
                    key={key}
                    className="trade-chart-draw-toolbar-icon"
                    onClick={this.drawMark(key)}>
                    <i className={icon}/>
                  </li>
                )
              })
            }
            <div
              className="trade-chart-draw-toolbar-icon"
              onClick={this.onDelete}>
              <i className="icon-delete"/>
            </div>
          </Scrollbars>
        </ul>
        <div className="trade-original-view-container">
          <div
            id="k_chart"
            style={ !this.state.isShowTechnicalIndicator ? { height: '100%' } : {}}
            className="trade-original-view"/>
          {
            this.state.isShowTechnicalIndicator &&
            <ul
              className="trade-original-view-technical-indicator-container">
              {
                technicalIndicatorTypes.map(technicalIndicatorType => {
                  return (
                    <li
                      className={`trade-original-view-technical-indicator ${this.state.currentTechnicalIndicatorType === technicalIndicatorType && 'trade-original-view-technical-indicator-selected'}`}
                      onClick={this.changeTechnicalIndicator(technicalIndicatorType)}>
                      {technicalIndicatorType}
                    </li>
                  )
                })
              }
            </ul>
          }
        </div>
        {
          this.loading && <Loading/>
        }
        {
          this.showSettingModal &&
          <SettingModal
            theme={theme}
            onClose={this.closeSettingModal}/>
        }
      </div>
    )
  }
}

export default OriginalView
